package com.iflytek.jzcpx.procuracy.card.common.enums;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;

import com.google.common.collect.Lists;
import com.iflytek.jzcpx.procuracy.card.component.ElleFieldExtractFunctionFactory;
import com.iflytek.jzcpx.procuracy.card.component.FieldConvertors;
import com.iflytek.jzcpx.procuracy.card.config.ZdbmConfig;
import com.iflytek.jzcpx.procuracy.card.entity.CardFormField;
import com.iflytek.jzcpx.procuracy.card.pojo.ElleResultData;
import com.iflytek.jzcpx.procuracy.tools.elle.ElleTextTypeEnum;
import org.apache.commons.lang3.StringUtils;

import static com.iflytek.jzcpx.procuracy.tools.elle.ElleTextTypeEnum.qsyjs;
import static com.iflytek.jzcpx.procuracy.tools.elle.ElleTextTypeEnum.tqpzdbs;

/**
 * 嫌疑人从表数据字段
 *
 * @author <a href=mailto:ktyi@iflytek.com>伊开堂</a>
 * @date 2019/10/21 09:10
 */
public enum XyrCbsjFieldEnum {
    /** 嫌疑人强制措施 - 强制措施 */
    QZCSQK_QZCS("强制措施", "T_TYYW_GG_QZCSQK", "QZCS", Lists.newArrayList(qsyjs,tqpzdbs),ElleResultData.CompulsoryMeasureCondition::getCompulsoryMeasure, 300,"强制措施"),
    //1.当强制措施是拘传、刑事拘留、逮捕这三种情况时，对应的是填强制措施羁押地点；
    //2.当强制措施是取保候审时，对应的是填取保候审地点；
    //3.当强制措施是监视居住和指定居所监视居住时，对应的是填监视居住地点
    //强制措施羁押地点
    QZCSJYDD("强制措施羁押地点", "T_TYYW_GG_QZCSQK","QZCSJYDD",Arrays.asList("拘传", "刑事拘留","逮捕"),ElleResultData.CompulsoryMeasureCondition::getCompulsoryMeasureAdd,Lists.newArrayList(qsyjs,tqpzdbs)),
    //监视居住地点
    JZJSDD("监视居住地点", "T_TYYW_GG_QZCSQK","JZJSDD",Arrays.asList("监视居住","指定居所监视居住时"),ElleResultData.CompulsoryMeasureCondition::getCompulsoryMeasureAdd,Lists.newArrayList(qsyjs,tqpzdbs)),
    //取保候审地点
    QBHSDD("取保候审地点", "T_TYYW_GG_QZCSQK","QBHSDD",Arrays.asList("取保候审"),ElleResultData.CompulsoryMeasureCondition::getCompulsoryMeasureAdd,Lists.newArrayList(qsyjs,tqpzdbs)),

    /** 嫌疑人强制措施 - 强制措施决定日期 */
    QZCSQK_QZCSCQRQ("强制措施决定日期", "T_TYYW_GG_QZCSQK", "QZCSCQRQ", Lists.newArrayList(qsyjs,tqpzdbs),
            ElleResultData.CompulsoryMeasureCondition::getCompulsoryMeasureDate, FieldConvertors.dateContactConvert(" 00:00:00")),

    /** 嫌疑人强制措施 - 执行机关名称 */
    QZCSQK_ZXJG("执行机关名称", "T_TYYW_GG_QZCSQK", "ZXJG", Lists.newArrayList(qsyjs,tqpzdbs), ElleResultData.CompulsoryMeasureCondition::getExecutiveOrgan, 300,ElleFieldExtractFunctionFactory.builExecutiveOrganFunc()),

    /** 嫌疑人强制措施 - 执行日期 一审公诉返回 审查逮捕不返回 */
    QZCSQK_ZXRQ("执行日期", "T_TYYW_GG_QZCSQK", "ZXRQ", Lists.newArrayList(qsyjs,tqpzdbs), ElleResultData.CompulsoryMeasureCondition::getExecutiveDate, FieldConvertors.dateContactConvert(" 00:00:00")),
    
    QZCSQK_PZJG("批准（决定）机关", "T_TYYW_GG_QZCSQK", "PZJG", Lists.newArrayList(qsyjs,tqpzdbs),ElleResultData.CompulsoryMeasureCondition::getApprovalAuthority,300,ElleFieldExtractFunctionFactory.builApprovalAuthorityFunc()),
    
    BZRXM("保证人姓名", "T_TYYW_GG_QZCSQK","BZRXM",Lists.newArrayList(qsyjs,tqpzdbs),ElleResultData.CompulsoryMeasureCondition::getGuarantorName,""),
    BZJ("保证金（万元）", "T_TYYW_GG_QZCSQK","BZJ",Lists.newArrayList(qsyjs,tqpzdbs),ElleResultData.CompulsoryMeasureCondition::getGuarantyFund,""),
   
    ;

    /** 名称描述 */
    private String mc;

    /** 实体表名 */
    private String stbm;

    /** 字段名称 */
    private String zdmc;
    
    /** 备注 */
    private String note;

    /** 字段来自哪种文书, 只有当文书是这种类型时, 这个字段才需要回填 */
    private Collection<ElleTextTypeEnum> supportElleTextType;
    

    /** 用来抽取elle引擎字段值的函数 */
    private Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> elleFieldExtractor;
    
    /** 用来抽取elle引擎字段值的函数 */
    private Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item[]> elleFieldItemsExtractor;
    
    /** 另外一种elle取值方法  通过案件信息转换**/
    private BiFunction<ElleResultData.CompulsoryMeasureCondition,ElleResultData,ElleResultData.Item> caseElleFieldExtractor;

    public BiFunction<ElleResultData.CompulsoryMeasureCondition,ElleResultData,ElleResultData.Item> getCaseElleFieldExtractor() {
		return caseElleFieldExtractor;
	}
    


	/** 字段文本值格式转换方法 */
    private Function<String, String> convertFunc ;

    /** 类别名称, 如果为空则不需要解析字段编码值 */
    private String lbmc;

    /** 字段文本值长度限制, 需要对照赛威讯案卡数据结构赋值 */
    private int zdwbzLimitSize = 300;
    
    /** 字典中存在什么样值时候才可以返回 字典值集合 */
    private List<String> dictionList;
    
    public List<String> getDictionList() {
		return dictionList;
	}
    
    XyrCbsjFieldEnum(String mc, String stbm, String zdmc , Collection<ElleTextTypeEnum> supportElleTextType, 
    		Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item[]> elleFieldItemsExtractor,String note){
    	this.mc=mc;
    	this.stbm=stbm;
    	this.zdmc=zdmc;
    	this.supportElleTextType=supportElleTextType;
    	this.elleFieldItemsExtractor=elleFieldItemsExtractor;
    	this.note=note;
    	
    }
    
    XyrCbsjFieldEnum(String mc, String stbm, String zdmc, List<String> dictionList ,Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> elleFieldExtractor	, 
    		Collection<ElleTextTypeEnum> supportElleTextType){
    	this.mc=mc;
    	this.stbm=stbm;
    	this.zdmc=zdmc;
    	this.dictionList=dictionList;
    	this.supportElleTextType=supportElleTextType;
    	this.elleFieldExtractor=elleFieldExtractor;
    	this.elleFieldExtractor=elleFieldExtractor;
    	
    }
    
    XyrCbsjFieldEnum(String mc,String stbm,String zdmc,Collection<ElleTextTypeEnum> supportElleTextType,
    		Function<ElleResultData.CompulsoryMeasureCondition, 
    		ElleResultData.Item>elleFieldExtractor,int zdwbzLimitSize,
    		BiFunction<ElleResultData.CompulsoryMeasureCondition,ElleResultData,ElleResultData.Item> caseElleFieldExtractor)
    {
    	this.mc=mc;
    	this.stbm=stbm;
    	this.zdmc=zdmc;
    	this.supportElleTextType=supportElleTextType;
    	this.elleFieldExtractor=elleFieldExtractor;
    	this.zdwbzLimitSize=zdwbzLimitSize;
    	this.caseElleFieldExtractor=caseElleFieldExtractor;
    }
    
    XyrCbsjFieldEnum(String mc, String zdmc, List<String> dictionList,Function<ElleResultData.CompulsoryMeasureCondition, 
    		ElleResultData.Item> elleFieldExtractor,Collection<ElleTextTypeEnum> supportElleTextType) {
        this.mc = mc;
        this.zdmc = zdmc;
        this.dictionList = dictionList;
        this.elleFieldExtractor = elleFieldExtractor;
        this.supportElleTextType=supportElleTextType;
    }
    
    XyrCbsjFieldEnum(String mc,String stbm, String zdmc, Collection<ElleTextTypeEnum> supportElleTextType,
            Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> elleFieldExtractor, Collection<ElleTextTypeEnum> cardDocumentType) {
        this.mc = mc;
        this.zdmc = zdmc;
        this.supportElleTextType = supportElleTextType;
        this.elleFieldExtractor = elleFieldExtractor;
    }
    
	XyrCbsjFieldEnum(String mc, String zdmc, Collection<ElleTextTypeEnum> supportElleTextType,
            Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item[]> elleFieldItemsExtractor) {
        this.mc = mc;
        this.zdmc = zdmc;
        this.supportElleTextType = supportElleTextType;
        this.elleFieldItemsExtractor = elleFieldItemsExtractor;
    }

    XyrCbsjFieldEnum(String mc, String stbm, String zdmc, Collection<ElleTextTypeEnum> supportElleTextType,
            Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> elleFieldExtractor, int zdwbzLimitSize, String lbmc) {
        this.mc = mc;
        this.stbm = stbm;
        this.zdmc = zdmc;
        this.supportElleTextType = supportElleTextType;
        this.elleFieldExtractor = elleFieldExtractor;
        this.zdwbzLimitSize = zdwbzLimitSize;
        this.lbmc = lbmc;
    }

    XyrCbsjFieldEnum(String mc, String stbm, String zdmc, Collection<ElleTextTypeEnum> supportElleTextType,
            Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> elleFieldExtractor, int zdwbzLimitSize) {
        this.mc = mc;
        this.stbm = stbm;
        this.zdmc = zdmc;
        this.supportElleTextType = supportElleTextType;
        this.elleFieldExtractor = elleFieldExtractor;
        this.zdwbzLimitSize = zdwbzLimitSize;
    }

    XyrCbsjFieldEnum(String mc, String stbm, String zdmc, Collection<ElleTextTypeEnum> supportElleTextType,
            Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> elleFieldExtractor) {
        this.mc = mc;
        this.stbm = stbm;
        this.zdmc = zdmc;
        this.supportElleTextType = supportElleTextType;
        this.elleFieldExtractor = elleFieldExtractor;
    }

    XyrCbsjFieldEnum(String mc, String stbm, String zdmc, Collection<ElleTextTypeEnum> supportElleTextType,
            Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> elleFieldExtractor, Function<String, String> convertFunc) {
        this.mc = mc;
        this.stbm = stbm;
        this.zdmc = zdmc;
        this.supportElleTextType = supportElleTextType;
        this.elleFieldExtractor = elleFieldExtractor;
        this.convertFunc = convertFunc;
        this.supportElleTextType=supportElleTextType;
    }

    /** 根据已保存的字段数据解析字段编码值 */
    public static String convertZdbmzForBdjg(CardFormField field) {
        if (field == null) {
            return "";
        }

        String zdwbz = field.getZdwbz();
        String zdbmz = field.getZdbmz();
        String stbm = field.getStbm();
        String zdmc = field.getZdmc();
        XyrCbsjFieldEnum fieldEnum = parseByStbmAndZdmc(stbm, zdmc);
        if (fieldEnum != null) {
            // 字段有类别名称配置, 说明字段有编码值配置, 因此需要返回字段编码值, 否则将字段文本值作为编码值返回
            return StringUtils.isNotBlank(fieldEnum.getLbmc()) ? zdbmz : zdwbz;
        }
        else {
            return StringUtils.isNotBlank(zdbmz) ? zdbmz : zdwbz;
        }
    }

    public static XyrCbsjFieldEnum parseByStbmAndZdmc(String stbm, String zdmc) {
        if (StringUtils.isAnyBlank(stbm, zdmc)) {
            return null;
        }
        for (XyrCbsjFieldEnum fieldEnum : values()) {
            if (fieldEnum.getStbm().contains(stbm) && fieldEnum.getZdmc().equals(zdmc)) {
                return fieldEnum;
            }
        }
        return null;
    }

    public String getLbmc() {
        return this.lbmc;
    }

    public String getStbm() {
        return stbm;
    }

    public String getMc() {
        return mc;
    }

    public String getZdmc() {
        return zdmc;
    }

    public Collection<ElleTextTypeEnum> getSupportElleTextType() {
        return supportElleTextType;
    }

    public Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item> getElleFieldExtractor() {
        return elleFieldExtractor;
    }
    
    public Function<ElleResultData.CompulsoryMeasureCondition, ElleResultData.Item[]> getElleFieldItemsExtractor() {
		return elleFieldItemsExtractor;
	}

	/** 字段文本值转换处理 */
    public String convertZdwbz(String input) {
    	if(null == convertFunc) {
    		return input;
    	}
        String zdwbz = convertFunc.apply(input);
        // 截断, 防止文本超长
        return StringUtils.substring(zdwbz, 0, zdwbzLimitSize);
    }

    /** 字段编码值转换处理, 在回填到表单结构时调用 */
    public String convertZdbmzForBdjg(String zdwbz, ZdbmConfig zdbmConfig) {
        // 解析字段编码值，如果字段没有配置编码值，则把文本值填入编码值字段
        // 如果有配置编码值，且能解析出对应编码值则填入编码值字段，否则不填
        if (StringUtils.isBlank(zdwbz) || zdbmConfig == null || StringUtils.isBlank(this.lbmc)) {
            return zdwbz;
        }

        return zdbmConfig.getZdbm(this.lbmc, zdwbz);
    }

    /** 字段编码值转换处理, 在保存字段到数据库时调用 */
    public String convertZdbmzForStore(String zdwbz, ZdbmConfig zdbmConfig) {
        // 解析字段编码值，如果字段没有配置编码值，则把文本值填入编码值字段
        // 但为了防止字段文本值超长导致存储失败, 因此使用空字符而不是文本值保存到编码值字段
        if (StringUtils.isBlank(zdwbz) || zdbmConfig == null || StringUtils.isBlank(this.lbmc)) {
            return "";
        }

        return zdbmConfig.getZdbm(this.lbmc, zdwbz);
    }
	
	public String getNote() {
		return note;
	}
}
